<template>
  <div class="notebook-workflow">
    <div class="notebook-workflow-actions">
      <el-select v-model="engine" placeholder="请选择" size="small">
        <el-option v-for="item in engineList" :key="item.id" :label="item.engineName" :value="item.id">
        </el-option>
      </el-select>
      <el-button size="mini" @click="running" v-hasPermi="['bigdata:project:flow:execute']">运行</el-button>
      <el-button size="mini" v-if="currentNotebook.type == 'batch'" @click="editToSchedule"
        v-hasPermi="['bigdata:project:flow:edit']">{{ added ? '更新调度' :
        '加入调度' }}</el-button>
      <el-button size="mini" @click="handleNotebook('delete')"
        v-hasPermi="['bigdata:project:flow:remove']">删除当前工作流</el-button>
      <!-- <el-dropdown v-if="!isDemo" @command="handleNotebook">
        <span class="el-dropdown-link">
          <i class="el-ksd-icon-document_22 font-22"></i><i class="el-ksd-icon-arrow_down_22 font-22"></i>
        </span>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item command='add'>{{ $t('workflow.createWorkflow') }}</el-dropdown-item>
          <el-dropdown-item command='rename'>{{ $t('rename') }}</el-dropdown-item>
          <el-dropdown-item command='clone'>{{ $t('clone') }}</el-dropdown-item>
          <el-dropdown-item command='delete'>
            <span class="txt-danger">{{ $t('workflow.deleteCurrentWorkflow') }}</span>
          </el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
      <span class="ml-15" v-if="!isDemo">
        <icon-btn icon="el-ksd-icon-save_22" :text="$t('workflow.saveAsNotebook')" :handler="saveAsNotebook" />
      </span>
      <SetDemo class="set-demo-wrap" v-if="userInfo.is_admin && !isDemo" :userInfo="userInfo"
        :activeNotebook="activeNotebook" @offlineTab="handleOfflineTab"
        @operateDemoSuccess="handleOperateDemoSuccess" /> -->
    </div>
    <div class="notebook-workflow-container" :class="showNodeEditor && 'right-bar'">
      <div class="notebook-workflow-container-l">
        <el-alert v-if="isDemo" type="info" show-icon>
          <div slot="title">
            {{ $t('workflow.readOnlyTip') }}<a href="javascript:;" @click="cloneWorkflow">{{ $t('workflow.clone')
              }}</a>
          </div>
        </el-alert>
        <Workflow ref="workflowWrapper" :selectNodeId="selectNodeId" :needTranformToLeft="needTranformToLeft"
          :showNodeEditor="showNodeEditor" :currentNotebook="currentNotebook" :activeNotebookId="activeNotebookId"
          @openNodeEditor="openNodeEditor" @changeNodeList="changeNodeList" :workflowActiveTab="activeName" />
      </div>
      <transition name="fade">
        <div class="notebook-workflow-container-r" v-if="showNodeEditor">
          <NodeEditor ref="nodeEditor" :nodeInfo="nodeInfo" @cancelEdit="cancelEdit" />
        </div>
      </transition>
    </div>

    <transition name="fade">
      <div class="notebook-workflow-excute-result" v-if="runResult">
        <WorkflowExcute :runResult="runResult" />
        <i class="el-icon-close close" @click="handleClose"></i>
      </div>
    </transition>

    <!-- 加入调度 -->
    <AddSchedule v-if="scheduleShow" />
  </div>
</template>

<script>
import Workflow from './workflow'
import NodeEditor from './components/NodeEditor'
import WorkflowPreview from './components/WorkflowPreview'
import WorkflowExcute from '@/components/WorkflowExcute'
import AddSchedule from '@/components/AddSchedule'
import SetDemo from '@/components/SetDemo'
import { Vue, Component, Watch } from 'vue-property-decorator'
import { mapActions, mapMutations, mapState, mapGetters } from 'vuex'
import { formatGetParams } from '@/util'

@Component({
  props: ['currentNotebook', 'activeNotebookId'],
  components: {
    Workflow,
    NodeEditor,
    WorkflowPreview,
    SetDemo,
    WorkflowExcute,
    AddSchedule
  },
  computed: {
    ...mapState({
      userInfo: state => state.user.userInfo,
      activeNotebook: state => state.notebook.activeNotebook,
      openedNotebooks: state => state.notebook.openedNotebooks,
    }),
    // ...mapState('DAGViewModal', {
    //   taskInfo: state => state.taskInfo
    // }),
    ...mapGetters(['isDemo'])
  },
  methods: {
    ...mapActions('CreateNoteBookModal', {
      callCreateNoteBookModal: 'CALL_MODAL'
    }),
    ...mapMutations({
      setOpenedNotebook: 'SET_OPENED_NOTEBOOK',
      changeActiveNotebook: 'SET_ACTIVE_NOTEBOOK',
      // setRunResult: 'SET_RUN_RESULT',
    }),
    // ...mapMutations('DAGViewModal', {
    //   setTaskInfo: 'SET_TASK_INFO'
    // }),
    ...mapActions({
      getEngineInfoList: 'GET_ENGINEINFO_LIST', // 列表
      runWorkflow: 'RUN_WORKFLOW',
      getNotebookInfo: 'GET_NOTEBOOK_INFO',
    }),
    ...mapActions('AddScheduleModal', {
      callAddScheduleModal: 'CALL_MODAL'
    }),
  }
})

export default class WorkflowWrapper extends Vue {
  engine = ''
  engineList = []
  hideDetail = false
  activeName = 'workflow'
  showNodeEditor = false
  runResult = ''
  nodeInfo = null
  needTranformToLeft = false
  selectNodeId = null
  show = true
  disableSaveToNotebook = false
  scheduleShow = false
  taskInfo = undefined
  added = false


  @Watch('activeNotebookId', { immediate: true })
  onActiveNotebookIdChange() {
    if (this.activeNotebookId == this.currentNotebook?.id) {
      this.checkNotebook()
    }
  }

  changeNodeList(list) {
    this.disableSaveToNotebook = !list.length
  }

  handleOperateDemoSuccess() {
    this.$emit('handleRefresh')
  }

  handleOfflineTab(tabId) {
    this.$emit('handleOfflineTab', tabId)
  }

  handleClose() {
    this.runResult = ''
  }

  async running() {
    try {
      const params = {
        engineId: this.engine
      }
      const res = await this.runWorkflow(params)
      this.runResult = res.result
      if (res.code == 100000) {
        this.msgSuccess('操作成功')
      }
      // this.checkResCode(res.code)
      // this.setRunResult(res.result)
    } catch (e) {
      console.log(e)
    }
  }

  editToSchedule() {
    this.scheduleShow = true
    if (this.taskInfo && this.taskInfo.scheduleInfo) {
      this.updateSchedule()
    } else {
      this.addToSchedule()
    }
  }
  // 加入
  // async addToSchedule() {
  //   try {
  //     // const { notebookInfo } = await this.callAddScheduleModal({ editInfo: { type: 'add', id: '' }, data: null })
  //     // if (notebookInfo.id) {
  //     //   await this.checkNotebook()
  //     //   this.scheduleShow = false
  //     // }
  //   } catch (err) {
  //     console.log(err)
  //   }
  // }

  async addToSchedule() {
    try {
      const data = {
        editInfo: { type: 'add', id: '' },
        data: {
          currentNotebook: this.activeNotebook,
          scheduleInfo: '',
          engineId: this.engine
        }
      }
      const { finished } = await this.callAddScheduleModal(data)
      // const { finished } = await this.callAddScheduleModal(this.activeNotebook)
      if (finished) await this.checkNotebook()
    } catch (err) {
      console.log(err)
    }
  }
  // 更新
  async updateSchedule() {
    this.$message.success(
      this.$t('schedules.updateSuccessMsg')
    )
    // try {
    //   const id = this.taskInfo.scheduleInfo.id
    //   const data = {
    //     editInfo: { type: 'edit', id },
    //     data: this.taskInfo
    //   }
    //   const { finished } = await this.callAddScheduleModal(data)
    //   if (finished) await this.checkNotebook()
    // } catch (err) {
    //   console.log(err)
    // }
  }
  async checkNotebook() {
    const params = formatGetParams({
      entity_id: this.activeNotebookId
    })
    try {
      const res = await this.getNotebookInfo(params)
      this.taskInfo = { scheduleInfo: res.result, currentNotebook: this.currentNotebook }
      this.added = res.result ? true : false
      // this.setTaskInfo({ taskInfo: { scheduleInfo: res.result, currentNotebook: this.currentNotebook } })
    } catch (e) {
      this.taskInfo = undefined
      // this.setTaskInfo({ taskInfo: undefined })
    }
  }
  openNodeEditor(node) {
    if (node && this.nodeInfo && (node.id === this.nodeInfo.id)) {
      return
    }
    if (!node) {
      this.showNodeEditor = false
      this.nodeInfo = null
      return
    }
    // 需要判断信息是否被修改 如果被修改则提示
    this.$nextTick(() => {
      const type = this.nodeInfo?.type
      const detailIsChanged = this.nodeInfo && this.$refs.nodeEditor?.$refs[`${type}Node`]?.detailIsChanged
      if (detailIsChanged) {
        this.$confirm(this.$t('workflow.changeNodeTip'), this.$t('tip'), {
          confirmButtonText: this.$t('ok'),
          cancelButtonText: this.$t('cancel'),
          type: 'warning',
          customClass: 'centerButton'
        }).then(() => {
          this.confirmOpenNewNode(node)
        })
      } else {
        this.confirmOpenNewNode(node)
      }
    })
  }
  confirmOpenNewNode(node) {
    this.selectNodeId = node.id
    this.showNodeEditor = true
    this.nodeInfo = node
    this.$nextTick(() => { // 为了计算画布是否需要向左移动
      const allWidth = this.$refs.workflowWrapper?.$el.offsetWidth
      const left = Number(node.left.split('px')[0])
      this.needTranformToLeft = allWidth <= left
    })
  }
  handleClick(tab) {
    const { uniq, type } = this.currentNotebook
    const temp = [...this.openedNotebooks]
    const index = temp.findIndex(v => v.uniq === uniq && v.type === type)
    temp[index].isPreviewMode = tab.name === 'notebook'
    this.changeActiveNotebook(temp[index])
    this.setOpenedNotebook(temp)
  }
  changeTabList(newNotebook) {
    this.$emit('changeTabList', newNotebook)
  }
  cancelEdit(needRefresh) {
    this.selectNodeId = null
    this.showNodeEditor = false
    this.nodeInfo = null
    if (needRefresh) {
      // 重新获取 node 信息
      this.$refs.workflowWrapper?.getWorkflowNodeList()
    }
  }
  async saveAsNotebook() {
    const { isSubmit, newNotobookInfo } = await this.callCreateNoteBookModal({ type: 'save-as-notebook' })
    const newInfo = {
      ...newNotobookInfo,
      uniq: 'notebook_' + newNotobookInfo.id
    }
    if (isSubmit) {
      this.$message({
        type: 'success',
        message: this.$t('workspace.createSuccess')
      })
      this.changeTabList(newInfo)
    }
  }
  cloneWorkflow() {
    this.handleNotebook('clone')
  }
  handleNotebook(type) {
    let handleName = ''
    switch (type) {
      case 'add':
        handleName = 'handleCreate'
        break
      case 'clone':
        handleName = 'handleClone'
        break
      case 'delete':
        handleName = 'handleDelete'
        break
      case 'rename':
        handleName = 'handleRename'
        break
      default:
        break
    }
    const node = {
      ...this.currentNotebook,
      type: 'workflow'
    }
    this.$emit(handleName, node)
  }
  async getEngineList() {
    try {
      const params = {
        pageNo: 1,
        pageSize: 10000,
      }
      const res = await this.getEngineInfoList(params)
      this.engineList = res?.result?.records ?? []
      this.engine = this.engineList[0].id
    } catch (e) {
      console.log(e)
    }
  }
  mounted() {
    this.getEngineList()
  }
}
</script>

<style lang="scss" scoped>
$tabs-header-height: 40px;
$tabs-operation-height: 37px;

.notebook-workflow {
  width: 100%;
  height: calc(100vh - $page-header-height - $page-breadcrumb-height - $page-breadcrumb-margin - $tabs-header-height);
  // height: calc(100vh - 100px);
  // padding-top: 10px;
  position: relative;

  >.el-tabs.tabs_button>.el-tabs__header {
    margin-left: calc(100% - 20px);
    transform: translateX(-100%);
  }

  &-actions {
    // position: absolute;
    // display: flex;
    // left: 30px;
    // top: 13px;
    display: flex;
    border: 1px solid $--line-border-color;
    border-top: none;
    padding: 2px 0;
    padding-left: 10px;

    .set-demo-wrap {
      margin-left: 15px;
    }

    .el-button {
      padding-top: 0;
      padding-bottom: 0;
    }

    .el-select {
      width: 200px;
      margin-right: 10px;
    }
  }

  &-container {
    width: 100%;
    height: calc(100vh - $page-header-height - $page-breadcrumb-height - $page-breadcrumb-margin - $tabs-header-height - $tabs-operation-height);
    // height: 100%;
    // height: calc(100vh - 150px);
    overflow-y: auto;
    border-top: 1px solid $--menu-active-bg-color;
    position: relative;
    padding-right: 0px;
    transition: all .2s ease-in;
    background-color: $--menu-active-bg-color;


    &.right-bar {
      padding-right: 400px;
    }

    &-l {
      width: 100%;
      height: 100%;
      background-image: url('../../assets/images/dot.svg');
    }

    &-r {
      position: absolute;
      right: 0px;
      top: 0;
      bottom: 0;
      margin: 5px;
      width: 400px;
      // height: 100%;
      border: 1px solid $--line-border-color;
      background-color: $--color-nav;
    }
  }

  &-excute-result {
    position: absolute;
    left: 0;
    bottom: 5px;
    width: 100%;
    padding: 5px;
    z-index: 9;

    .close {
      position: absolute;
      top: 10px;
      right: 10px;
      z-index: 999;
      cursor: pointer;
      color: $--mian-color;

      &:hover {
        color: $--menu-active-color;
      }
    }
  }
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity .2s;
}

.fade-enter,
.fade-leave-to {
  opacity: 0;
}
</style>
